package com.devilvan.betrice.qzone.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devilvan.betrice.request.component.HttpClientComponent;
import com.devilvan.betrice.download.component.BetriceDownloadComponent;
import com.devilvan.betrice.download.pojo.PictureSuffixConstant;
import com.devilvan.betrice.qzone.constant.QzoneAlbumConstant;
import com.devilvan.betrice.qzone.dto.QzoneAlbumHeaderDto;
import com.devilvan.betrice.qzone.dto.QzoneDownloadPictureDto;
import com.devilvan.betrice.qzone.entity.FindAllDownloadEntity;
import com.devilvan.betrice.qzone.mapper.QzoneAlbumHeaderMapper;
import com.devilvan.betrice.qzone.po.QzoneAlbumHeaderPo;
import com.devilvan.betrice.qzone.repository.QzoneAlbumHeaderRepository;
import com.devilvan.betrice.qzone.service.QzoneAlbumService;
import com.devilvan.betrice.util.UCopy;
import com.devilvan.betrice.util.UEmpty;
import com.devilvan.betrice.util.UValidAssem;
import org.apache.http.client.methods.HttpRequestBase;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.Resource;
import java.io.File;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Evad.Wu
 * @Description QQ空间 用户相册 业务逻辑层
 * @date 2022-09-11
 */
@Service
public class QzoneAlbumServiceImpl extends ServiceImpl<QzoneAlbumHeaderMapper, QzoneAlbumHeaderPo> implements QzoneAlbumService {
    @Resource(name = "betriceRedisTemplate")
    private RedisTemplate<String, Object> betriceRedisTemplate;
    @Resource(name = "httpClientComponent")
    private HttpClientComponent httpClientComponent;
    @Resource(name = "betriceDownloadComponent")
    private BetriceDownloadComponent betriceDownloadComponent;
    @Resource(name = "threadPoolExecutor")
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource(name = "qzoneAlbumHeaderRepository")
    private QzoneAlbumHeaderRepository qzoneAlbumHeaderRepository;
    @Resource(name = "qzoneAlbumHeaderMapper")
    private QzoneAlbumHeaderMapper qzoneAlbumHeaderMapper;

    @Override
    public List<QzoneAlbumHeaderPo> saveUpdateBatch(List<QzoneAlbumHeaderDto> qzoneAlbumHeaderDtoList) {
        List<QzoneAlbumHeaderPo> qzoneAlbumHeaderPoList = UCopy.fullCopyCollections(qzoneAlbumHeaderDtoList, QzoneAlbumHeaderPo.class);
        return qzoneAlbumHeaderRepository.saveAllAndFlush(qzoneAlbumHeaderPoList);
    }

    @Override
    public void downloadPhoto(QzoneDownloadPictureDto qzoneDownloadPictureDto) {
        String ownerUin = qzoneDownloadPictureDto.getOwnerUin();
        String exportPath = qzoneDownloadPictureDto.getExportPath();
        String suffix = validSuffix(qzoneDownloadPictureDto.getSuffix());
        if (null == suffix) {
            return ;
        }
        int current = 1;
        while (true) {
            Page<QzoneAlbumHeaderPo> page = new Page<>(current, 100);
            List<FindAllDownloadEntity> downloadEntityList = qzoneAlbumHeaderMapper.findAllDownloadEntity(ownerUin, page);
            if (UEmpty.isEmpty(downloadEntityList)) {
                break;
            }
            threadPoolExecutor.execute(() -> {
                ReentrantLock reentrantLock = new ReentrantLock();
                reentrantLock.lock();
                try {
                    String assemExportPath;
                    String assemFileName;
                    for (FindAllDownloadEntity findAllDownloadEntity : downloadEntityList) {
                        try {
                            HttpRequestBase httpRequest = httpClientComponent.generateHttpRequest(RequestMethod.GET, findAllDownloadEntity.getUrl());
                            assemExportPath = this.assemExportPath(exportPath, ownerUin, findAllDownloadEntity.getTopicName());
                            assemFileName = this.assemFileName(findAllDownloadEntity.getTopicId(), findAllDownloadEntity.getId());
                            String path = this.assemDownloadPath(assemExportPath, assemFileName, suffix);
                            betriceDownloadComponent.download(httpRequest, path);
                        } catch (Exception e) {
                            e.printStackTrace();
                            betriceRedisTemplate.opsForList().rightPush(QzoneAlbumConstant.KEY_QZONE_ALBUM_DOWNLOAD_EXCEPTION, findAllDownloadEntity.getId());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            });
            current++;
        }
    }

    private String assemFileName(String topicId, String id) {
        return topicId + "-" + id;
    }

    /**
     * 根据父路径、QQ号、相册名称，适配导出文件夹的路径
     *
     * @param exportPath 父路径
     * @param ownerUin   QQ号
     * @param topicName  相册名称
     * @return 装配完成的导出路径
     */
    @SuppressWarnings(value = "all")
    private String assemExportPath(String exportPath, String ownerUin, String topicName) {
        String split = "\\";
        StringBuilder sb = new StringBuilder();
        // 如果路径后没加\\
        if (!exportPath.endsWith(split)) {
            sb.append(exportPath).append(split);
        }
        StringBuilder ownerUinPath = sb.append(exportPath).append(ownerUin);
        File ownerUinFilePath = new File(ownerUinPath.toString());
        if (!ownerUinFilePath.exists()) {
            ownerUinFilePath.mkdir();
        }
        StringBuilder topicNamePath = ownerUinPath.append(split).append(topicName);
        File topicNameFilePath = new File(topicNamePath.toString());
        if (!topicNameFilePath.exists()) {
            topicNameFilePath.mkdir();
        }
        topicNamePath.append(split);
        return sb.toString();
    }

    /**
     * 根据报文中的suffix字段，验证是否符合图片后缀
     *
     * @param suffix 报文中的后缀
     * @return 验证后的后缀
     */
    private String validSuffix(String suffix) {
        PictureSuffixConstant[] constants = PictureSuffixConstant.values();
        for (PictureSuffixConstant constant : constants) {
            if (constant.name().equalsIgnoreCase(suffix)) {
                return constant.getValue();
            }
        }
        return null;
    }

    /**
     * 装配下载路径
     *
     * @param path     文件路径
     * @param fileName 文件名
     * @param suffix   后缀
     * @return 完整的文件路径
     */
    private String assemDownloadPath(String path, String fileName, String suffix) {
        return UValidAssem.validExportPath(path, fileName, suffix);
    }
}
